
#include "at32f403a_407_board.h"

/* delay macros */
#define STEP_DELAY_MS 50

/* delay variable */
static __IO uint32_t fac_us;
static __IO uint32_t fac_ms;

/* support printf function, usemicrolib is unnecessary */
#if (__ARMCC_VERSION > 6000000)
__asm(".global __use_no_semihosting\n\t");
void _sys_exit(int x)
{
  x = x;
}
/* __use_no_semihosting was requested, but _ttywrch was */
void _ttywrch(int ch)
{
  ch = ch;
}
FILE __stdout;
#else
#ifdef __CC_ARM
#pragma import(__use_no_semihosting)
struct __FILE
{
  int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
  x = x;
}
/* __use_no_semihosting was requested, but _ttywrch was */
void _ttywrch(int ch)
{
  ch = ch;
}
#endif
#endif

#if defined(__GNUC__) && !defined(__clang__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

/**
 * @brief  retargets the c library printf function to the usart.
 * @param  none
 * @retval none
 */
PUTCHAR_PROTOTYPE
{
  while (usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET)
    ;
  usart_data_transmit(PRINT_UART, ch);
  return ch;
}

/**
 * @brief  initialize uart
 * @param  baudrate: uart baudrate
 * @retval none
 */
void uart_print_init(uint32_t baudrate)
{
  gpio_init_type gpio_init_struct;

  /* enable the uart and gpio clock */
  crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);
  crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);

  gpio_default_para_init(&gpio_init_struct);

  /* configure the uart tx pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(PRINT_UART_TX_GPIO, &gpio_init_struct);

  /* configure uart param */
  usart_init(PRINT_UART, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(PRINT_UART, TRUE);
  usart_enable(PRINT_UART, TRUE);
}

/**
 * @brief  configures the different system clocks.
 * @param  none
 * @retval none
 */
void crm_configuration(void)
{
  /* dma clock enable */
  crm_periph_clock_enable(SPI_Slave_DMA_CLK, TRUE);

  // SPI,LED,CAN都使用了GPIOA管脚，这里只需要开启一次时钟就ok
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  /* spi clock enable */
  crm_periph_clock_enable(SPI_Slave_CLK, TRUE);

  // ADC时钟
  crm_periph_clock_enable(CRM_ADC3_PERIPH_CLOCK, TRUE);
  crm_adc_clock_div_set(CRM_ADC_DIV_6);
  // CAN时钟
  crm_periph_clock_enable(CRM_CAN1_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_CAN2_PERIPH_CLOCK, TRUE);
  //复用时钟
  crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
	//DMA时钟
  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE);
	//定时器时钟
		crm_periph_clock_enable(CRM_TMR4_PERIPH_CLOCK, TRUE);
}

void LED_Init()
{
  gpio_init_type gpio_init_struct;

  /* set default parameter */
  gpio_default_para_init(&gpio_init_struct);

  /* configure the led gpio */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins = LED_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LED_GPIO, &gpio_init_struct);
  gpio_bits_set(GPIOA, GPIO_PINS_3);
}

/**
 * @brief  initialize delay function
 * @param  none
 * @retval none
 */
void delay_init()
{
  /* configure systick */
  systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
  fac_us = system_core_clock / (1000000U);
  fac_ms = fac_us * (1000U);
}

/**
 * @brief  inserts a delay time.
 * @param  nus: specifies the delay time length, in microsecond.
 * @retval none
 */
void delay_us(uint32_t nus)
{
  uint32_t temp = 0;
  SysTick->LOAD = (uint32_t)(nus * fac_us);
  SysTick->VAL = 0x00;
  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  do
  {
    temp = SysTick->CTRL;
  } while ((temp & 0x01) && !(temp & (1 << 16)));

  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  SysTick->VAL = 0x00;
}

/**
 * @brief  inserts a delay time.
 * @param  nms: specifies the delay time length, in milliseconds.
 * @retval none
 */
void delay_ms(uint16_t nms)
{
  uint32_t temp = 0;
  while (nms)
  {
    if (nms > STEP_DELAY_MS)
    {
      SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms);
      nms -= STEP_DELAY_MS;
    }
    else
    {
      SysTick->LOAD = (uint32_t)(nms * fac_ms);
      nms = 0;
    }
    SysTick->VAL = 0x00;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    do
    {
      temp = SysTick->CTRL;
    } while ((temp & 0x01) && !(temp & (1 << 16)));

    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
    SysTick->VAL = 0x00;
  }
}

/**
 * @brief  inserts a delay time.
 * @param  sec: specifies the delay time, in seconds.
 * @retval none
 */
void delay_sec(uint16_t sec)
{
  uint16_t index;
  for (index = 0; index < sec; index++)
  {
    delay_ms(500);
    delay_ms(500);
  }
}

void LED_ON(void)
{
		gpio_bits_reset(GPIOA,GPIO_PINS_3);
}

void LED_OFF(void)
{
		gpio_bits_set(GPIOA,GPIO_PINS_3);
}


uint16_t  float_to_uint(float v,float v_min,float v_max,uint32_t width)
{
	float temp;
	int32_t utemp;
	temp = ((v-v_min)/(v_max-v_min))*((float)width);
	utemp = (int32_t)temp;
	if(utemp < 0)
		utemp = 0;
	if(utemp > width)
		utemp = width;
	return utemp;
}


//限制
float Constraint(float Value,float Min,float Max)
{
  if (Value >= Max)
  {
    Value = Max;
  }
  if (Value <= Min)
  {
    Value = Min;
  }
  return Value;
}

void at32_board_init()
{
  //初始化延时函数
  delay_init();
  //初始化各个外设的时钟
  crm_configuration();

  // 初始化各个外设
  uart_print_init(115200);

  LED_Init();
  SPI_Init();
  CAN_Init();
  ADC_Init();
  // TIM4_Init();

  //需要等待延时来等ADC进行校准
	delay_ms(300);
	adc_ordinary_software_trigger_enable(ADC3, TRUE);
}
